查看原文
其他

Flutter 2.8 | 一文解读重点更新

Flutter 谷歌开发者 2022-08-06

作者 / Chris Sells, Flutter 开发者体验产品经理


又到了北半球每年的这个时节: 树叶变黄、气温下降,而今年的最终稳定版本也在此时发布: Flutter 2.8 闪亮登场!这个版本凝聚了 207 位贡献者和 178 位审阅者的辛勤付出,合并了 2,424 个 PR,并解决了 2,976 个问题。在这里,我们要特别感谢此版本的杰出社区贡献者 Bartosz Selwesiuk,作为 Very Good Ventures 的 Flutter 工程师,他提供了 23 个 PR,其中大部分主要 "专注于" (原文如此) 面向 Web 的摄像头插件。


所有人的通力合作给引擎和 Flutter DevTools 带来了显著的性能改进、稳定的 Google Mobile Ads SDK for Flutter 版本、一系列全新的 Firebase 功能和改进、WebView 3.0、一批新的 Flutter Favorite package、朝着稳定版桌面端支持更进一步的大量更新,以及支持更多 package (包括 Firebase) 的新版本 DartPad。这应该是今年发布的最后一个版本,相信不负大家的期待。我们一起走进 Flutter 2.8!



性能


一如往常,Flutter 的第一要务是质量。我们的绝大部分工作旨在确保 Flutter 在其支持的设备上尽可能顺畅和稳健地运行。


启动

此版本对应用启动延迟进行了改进。我们通过 Google Pay 对这些改进进行了测试。作为一个热门的大型应用,Google Pay 拥有超过 100 万行代码,可以确保这些改进能够在现实环境中产生显著的积极影响。所有相关改进使 Google Pay 在低端 Android 设备上运行时的启动延迟降低了 50%,在高端设备上降低了 10%。


对于 Flutter 影响 Dart VM 垃圾回收策略机制的改进,现在有助于避免在应用启动序列中出现错误的垃圾回收 (GC) 周期。例如,在 Android 上渲染第一帧之前,Flutter 现在只通知 Dart VM "TRIM_LEVEL_RUNNING_CRITICAL" 及以上的内存压力。在本地测试中,此改进将低端设备上的第一帧时间减少了多达 300 毫秒。


  • #90551: 只通知 Dart VM "TRIM_LEVEL_RUNNING_CRITICAL" 及以上的内存压力
    https://github.com/flutter/flutter/issues/90551


出于谨慎考虑,在之前的版本中,Flutter 在创建平台视图时会阻塞平台线程。经过仔细推敲和测试,我们确定可以移除一些序列化操作,这使得在低端设备上启动 Google Pay 时减少了超过 100 毫秒的阻塞。


  • #29145: 在 UI/Raster 线程上不要对 Shell::OnCreatePlatformView 进行序列化操作
    https://github.com/flutter/engine/pull/29145#pullrequestreview-778935616
  • #91711: UI 线程上的 Shell::OnPlatformViewCreated 不应进行序列化
    https://github.com/flutter/flutter/issues/91711


以前,设置默认字体管理器会在设置第一个 Dart Isolate 时引入人为延迟。延迟默认字体管理器设置,使其与 Dart Isolate 设置同时运行,既改善了启动延迟时间,又使得上述优化的效果更加明显,因为主要的瓶颈就在这里。


  • #29291: 延迟默认字体管理器,使其与 Isolate 设置同时运行

    https://github.com/flutter/engine/pull/29291


内存
由于 Flutter 会急切地加载 Dart VM 的 "Service Isolate",其 AOT 代码与应用捆绑在一起,以便 Flutter 可以同时将两者读入内存,因此以内存受限设备为目标平台的 Flutter 开发者在进行性能跟踪时遇到了问题。对于使用 2.8 版本的 Android 设备,Dart VM 的 Service Isolate 会被分离到自己的软件包内,可单独加载,因此在需要使用 Service Isolate 之前,可以节省多达 40 MB 的内存。Dart VM 会通知操作系统,AOT 程序使用的内存分页被备份到了一个可能无需再次读取的文件里,这使得内存占用量进一步减少达 10%。因此,之前用于保存文件备份数据副本的分页可以被回收,并用于其他用途。


  • #91382: 引擎不应使用应用快照加载 VM 服务
    https://github.com/flutter/flutter/issues/91382
  • #29245: 构建一个用于在 Android 分析模式启动 Service Isolate 的专用快照
    https://github.com/flutter/engine/pull/29245
  • #92120: 为提供给 Dart VM 的类型映射提供提示
    https://github.com/flutter/flutter/issues/92120

性能分析
有时,开发者希望能够同时查看来自 Flutter 的性能跟踪数据以及 Android 原生跟踪事件。此外,他们也会希望能查看以发布模式构建的应用中的跟踪事件,以便深入了解所部署的应用中的性能问题。为此,2.8 稳定版现在会将跟踪事件发送到 Android systrace 记录器 (如果其已在应用启动时启用),同时,即使 Flutter 应用在发布模式下构建,这些事件也会发送出来。
△ Flutter 跟踪事件现在显示在 Android systrace 记录工具中 (见底端)
  • #28903: 如在应用启动时启用 systrace,则使用 systrace 记录器,并在 Android 发布模式下启用 systrace
    https://github.com/flutter/engine/pull/28903

此外,为了创建卡顿更少的动画,一些开发者希望性能跟踪记录中包含更多关于光栅缓存行为的信息,这使得 Flutter 能够对昂贵和重复使用的图片进行图块搬移,无需在每一帧上重新进行绘制。性能跟踪记录中的新流程事件现在允许开发者跟踪光栅缓存图片的生命周期。


  • #92286: 为光栅缓存的生成至删除事件添加流程或异步事件
    https://github.com/flutter/flutter/issues/92286

Flutter DevTools
在调试性能问题方面,此版本的 DevTools 添加了新的 "增强跟踪 (Enhance Tracing)" 功能,以帮助用户诊断由成本高昂的构建、布局和绘制操作引起的界面卡顿。

  • #3451: 在性能页面增加跟踪绘制和跟踪布局开关
    https://github.com/flutter/devtools/pull/3451

启用任一跟踪功能时,时间轴将根据选项相应地包含新的 "已构建 widget"、"已布局渲染对象" 和 "已绘制渲染对象" 事件。

另外,此版本的 DevTools 添加了新功能来分析应用启动时的性能表现。此剖析文件包含从 Dart VM 初始化到第一个 Flutter 帧渲染完成的所有 CPU 采样。在点击 "剖析应用启动 (Profile app starup)" 按钮并加载应用启动剖析文件后,您将看到剖析文件的 "AppStartUp" 用户标签已被选中。您还可以通过在列表中选择这个用户标签过滤器 (如果可用),来加载应用启动剖析文件。选择此标签会显示您应用启动的剖析数据。

  • #3357: 增加应用启动剖析功能,以及改进 CPU 剖析缓存
    https://github.com/flutter/devtools/pull/3357

Web 版平台视图
并不是仅有 Android 和 iOS 平台的性能得到了改进,此版本还改进了 Web 版 Flutter 平台视图的性能。如果您不熟悉平台视图,这里简单介绍一下: 它是 Flutter 供您托管来自应用底层平台的原生界面组件的方式。Web 版 Flutter 使用 HtmlElementView widget 实现这一功能,用于在 Flutter web 应用中托管 HTML 元素。如果您正在使用 google_maps_flutter 或 video_player 插件的 Web 版本,或者您正在遵循 Flutter 团队关于如何在 Web 平台优化显示图像的建议,那么您就是在使用平台视图。


  • HtmlElementView
    https://api.flutter.cn/flutter/widgets/HtmlElementView-class.html
  • 在 Web 中展示图片
    https://flutter.cn/docs/development/platform-integration/web-images#use-img-in-a-platform-view


在 Flutter 之前的版本中,嵌入平台视图会立即构建一个新的 canvas,每增加一个平台视图,都会添加一个新的 canvas。这些额外生成的 canvas 成本高昂,因为每个 canvas 都是整个窗口的大小。而在新版本中,我们复用了为之前的平台视图创建的 canvas,因此相比较之前每秒承担 60 倍的成本,如今在整个应用的生命周期内只需要承担一次成本即可。这意味着您可以在 Web 应用中创建多个 HtmlElementView 而不损失性能,同时可减少使用平台视图时的滚动卡顿。


  • #28087: 优化特殊用例下的 CanvasKit 平台视图
    https://github.com/flutter/engine/pull/28087


生态系统


Flutter 不仅仅是框架、引擎和工具: pub.dev 上有超过 20,000 个与 Flutter 兼容的 package 和插件,而且每天还在不断产生更多的内容。Flutter 开发者日常大量互动的内容构成了一个更为庞大的生态系统,让我们一起来看看自上个版本以来 Flutter 生态系统的发展吧。


Flutter Ads 正式发布

首先,也是最重要的是,Google Mobile Ads SDK for Flutter 已正式发布

此版本支持 5 种广告格式,集成了 AdMob 和 Ad Manager 支持,并包含新中介功能的测试版,可帮助您优化广告效果。有关将 Google Ads 集成到 Flutter 应用以及其他获利方案的更多信息,请查看有关获利的详细信息:

https://flutter.cn/monetization


WebView 3.0

这次 Flutter 还带来了 webview_flutter 插件的 3.0 版本:

https://pub.flutter-io.cn/packages/webview_flutter


因为新功能数量众多,以及 Web 视图在 Android 上运行时会出现潜在的重大变更,我们提高了版本号。在 webview_flutter 的上一版本中,我们已提供混合集成模式,但没有将其设为默认。混合集成修复了原先默认虚拟显示模式存在的若干问题。基于用户反馈和我们的问题追踪,我们认为是时候让混合集成变成默认模式了。此外,webview_flutter 也增加了若干呼声很高的功能:
  • 支持使用 POST 和 GET 填充内容 (#4450、#4479、#4480、#4573)
  • https://github.com/flutter/plugins/pull/4450
  • https://github.com/flutter/plugins/pull/4479
  • https://github.com/flutter/plugins/pull/4480
  • https://github.com/flutter/plugins/pull/4573

  • 从文件和字符串加载 HTML (#4446、#4486、#4544、#4558)
  • https://github.com/flutter/plugins/pull/4446
  • https://github.com/flutter/plugins/pull/4486
  • https://github.com/flutter/plugins/pull/4544
  • https://github.com/flutter/plugins/pull/4558

  • 透明背景支持 (#3431、#4569、#4570)
  • https://github.com/flutter/plugins/pull/3431
  • https://github.com/flutter/plugins/pull/4569
  • https://github.com/flutter/plugins/pull/4570

  • 在加载内容前写入 Cookie (#4555、#4556、#4557)
  • https://github.com/flutter/plugins/pull/4555
  • https://github.com/flutter/plugins/pull/4556
  • https://github.com/flutter/plugins/pull/4557

而且在 3.0 版本中,webview_flutter 还新增了对 Web 平台的初步支持。有许多人希望能在 Flutter Web 应用中托管 WebView,这可让他们通过单个源代码库来构建移动或 Web 应用。那如何在 Flutter Web 应用中托管 WebView 呢?代码如下:

import 'package:flutter/foundation.dart';import 'package:flutter/material.dart';import 'package:webview_flutter/webview_flutter.dart';import 'package:webview_flutter_web/webview_flutter_web.dart';
void main() { runApp(const MaterialApp(home: HomePage()));}
class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key);
@override State<HomePage> createState() => _HomePageState();}
class _HomePageState extends State<HomePage> { @override void initState() { super.initState();
// required while web support is in preview if (kIsWeb) WebView.platform = WebWebViewPlatform(); }
@override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: const Text('Flutter WebView example')), body: const WebView(initialUrl: 'https://flutter.dev'), );}

它在 Web 上运行时的效果也正如您预期的那样:

注意,当前 Web 端 webview_flutter 的实现有许多限制,因为它是借助 iframe 构建的,而 iframe 只能支持简单的网址加载,无法控制加载的内容或与其交互 (更多详细信息见 webview_flutter_web README)。但是,应大家需求,我们将提供 webview_flutter_web,作为未整合的插件供大家使用。如果您想一试,请将以下代码行添加到您的 pubspec.yaml 中:

dependencies: webview_flutter: ^3.0.0 webview_flutter_web: ^0.1.0 # add unendorsed plugin explicitly


  • Webview_flutter_web README
    https://pub.flutter-io.cn/packages/webview_flutter_web
  • 未整合的联合插件
    https://flutter.cn/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin

如果您对 webview_flutter v3.0 有任何反馈,无论是否基于 Web 端,请将其作为 WebView 问题提交至 Flutter repo。此外,如果您之前没有使用过 WebView 或想回顾一下其用法,请查看全新的 WebView Codelab,它会向您逐步介绍在 Flutter 应用中托管 Web 内容的过程。


  • 提交问题
    https://github.com/flutter/flutter/issues
  • WebView Codelab
    https://codelabs.developers.google.com/codelabs/flutter-webview

Flutter Favorites
Flutter 生态系统委员会再次举行会议,并将以下内容指定为 Flutter Favorite package:

https://flutter.cn/docs/development/packages-and-plugins/favorites#flutter-ecosystem--committee


  • 新 Router API 的三个自定义路由 package: beamer、routemaster 和 go_router

  • https://pub.flutter-io.cn/packages/beamer
  • https://pub.flutter-io.cn/packages/routemaster
  • https://pub.flutter-io.cn/packages/go_router


  • drift,重命名自 Flutter 和 Dart 中的一个已经可用且颇为流行的反应式持久性库,它建立于 sqlite 之上:

  • https://pub.flutter-io.cn/packages/drift
  • https://pub.flutter-io.cn/packages/sqlite3


  • freezed 是一个 Dart 的 "语言补丁",为定义模型、克隆对象、模式匹配等提供简单的语法
  • https://pub.flutter-io.cn/packages/freezed


  • dart_code_metrics

  • https://pub.flutter-io.cn/packages/dart_code_metrics


  • 此外还有几个好用的图形用户界面 package: flex_color_schemeflutter_svgfeedbacktoggle_switchauto_size_text
  • https://pub.flutter-io.cn/packages/flex_color_scheme

  • https://pub.flutter-io.cn/packages/flutter_svg

  • https://pub.flutter-io.cn/packages/feedback

  • https://pub.flutter-io.cn/packages/toggle_switch

  • https://pub.flutter-io.cn/packages/auto_size_text

△ Flexfold 应用就使用了 flex_color_scheme

祝贺这些 package 的作者,感谢您用自己的辛勤努力支持 Flutter 社区。如果您想要提名最喜欢的 Flutter package 来获得 Flutter Favorite 奖项,请遵循 Flutter Favorite 计划页面上的指南和说明:

https://flutter.cn/docs/development/packages-and-plugins/favorites


特定平台的 package
如果您是 package 作者,您必须确定自己准备支持哪些平台。如果您要用特定平台的原生代码来构建插件,您可以在项目的 pubspec.yaml 中使用 pluginClass 属性,用来表示提供该功能的原生类:

https://flutter.cn/docs/development/packages-and-plugins/developing-packages#plugin-platforms

flutter: plugin: platforms: android: package: com.example.hello pluginClass: HelloPlugin ios: pluginClass: HelloPlugin

然而,随着 Dart FFI 越来越成熟,您也有可能完全在 Dart 中实现特定平台的功能,就像 path_provider_windows package 那样。在这种情况下,没有任何原生类可以使用,但您仍然需要指定 package 只支持某些平台,您可以使用 dartPluginClass 属性代替:

flutter: plugin: implements: hello platforms: windows: dartPluginClass: HelloPluginWindows
  • Dart FFI
    https://dart.dev/guides/libraries/c-interop
  • path_provider_windows
    https://pub.flutter-io.cn/packages/path_provider_windows

有了这个设置,在没有任何原生代码的情况下,您也可以把 package 设置成只支持某些特定平台。您还必须提供 Dart 插件类,您可以通过仅 Dart 的平台实现官方文档中了解详情:

https://flutter.cn/docs/development/packages-and-plugins/developing-packages#dart-only-platform-implementations


Firebase
Flutter 生态系统的另一个重要部分是 FlutterFire,有 2/3 的 Flutter 应用在使用它。这个版本带来了一系列新功能,让使用 Flutter 和 Firebase 构建应用变得更加轻松:
  • 所有 FlutterFire 插件已从 Beta 版过渡到稳定版
  • Dartpad 中增加了对若干 Firebase 服务的支持
  • 用于更轻松构建身份验证和实时 Firestore 查询界面的库
  • 针对 Flutter 的新 Firestore 对象/文档映射 (Alpha 版)

生产质量
FlutterFire 插件已经基本从 Beta 版转换至稳定版:

http://firebase.flutter.dev/

Android、iOS 和 Web 平台中已经稳定的插件包括 Analytics、Dynamic Links、In-App Messaging、Performance Monitoring、Realtime Database、Remote Config 以及新增的 Installations。App Check 插件和 macOS 平台支持仍处于 Beta 版,因为 Firebase 库本身也处于 Beta 版阶段。如果您因为 FlutterFire 库还未就绪而犹豫是否要选择 Realtime Database、Analytics 或 Remote Config,那么请不用再担心了。现在它们已经是完全受支持的插件,可供生产使用。

  • Analytics
    https://firebase.flutter.dev/docs/analytics/overview
  • Dynamic Links
    https://firebase.flutter.dev/docs/dynamic-links/overview
  • In-App Messaging
    https://firebase.flutter.dev/docs/in-app-messaging/overview/
  • Performance Monitoring
    https://firebase.flutter.dev/docs/performance/overview
  • Realtime Database
    https://firebase.flutter.dev/docs/database/overview
  • Remote Config
    https://firebase.flutter.dev/docs/remote-config/overview
  • Installations
    https://firebase.flutter.dev/docs/installations/overview

仅使用 Dart 初始化 Firebase
随着 package 转向生产质量,我们增加了通过 Dart 在任何受支持平台上初始化 Firebase 的功能:

https://github.com/FirebaseExtended/flutterfire/pull/6549

import 'package:firebase_core/firebase_core.dart';import 'firebase_options.dart'; // generated via `flutterfire` CLI
Future<void> main() async { // initialize firebase across all supported platforms WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(MyApp());}

上面的代码使用适合每个受支持平台的选项初始化 Firebase 应用,这些选项在 firebase_options.dart 文件中定义,该文件包含每个平台的数据结构,如下所示:

static const FirebaseOptions web = FirebaseOptions( apiKey: 'AIzaSyCZFKryCEiKhD0JMPeq_weJguspf09h7Cg', appId: '1:111079797892:web:b9195888086158195ffed1', messagingSenderId: '111079797892', projectId: 'flutterfire-fun', authDomain: 'flutterfire-fun.firebaseapp.com', storageBucket: 'flutterfire-fun.appspot.com', measurementId: 'G-K029Y6KJDX',);

要收集每个平台初始化选项数据结构的数据,请使用新的 flutterfire CLI 工具:

https://pub.flutter-io.cn/packages/flutterfire_cli

此工具会深入挖掘平台特定子文件夹中的数据,以找到唯一的软件包 ID,然后用它来查找匹配平台特定应用的 Firebase 项目特定详细信息,如果没有查找到的话,甚至还会创建一个新的 Firebase 项目和/或新的平台特定应用。这意味着,您不再需要下载 json 文件并将其添加到 Android 项目、或下载 plist 文件并将其添加到 iOS 和 macOS 项目,或将代码粘贴到您 Web 项目的 index.html 中: 无论您的 Firebase 项目支持哪个平台,这段 Dart 代码都将为您的应用完成 Firebase 的初始化。请注意,要让 FlutterFire 应用正常工作,需要的初始化工作可能不止于此,例如,您可能需要将 Crashlytics 符号的创建集成到您的 Android 构建或 iOS 构建中,但在一个新的 Firebase 项目中,这些操作应该只需要几分钟就可以完成并顺利运行。


  • #7359: 自动注入 Firebase JS SDK
    https://github.com/FirebaseExtended/flutterfire/pull/7359
  • 将 Crashlytics 插件添加至应用
    https://firebase.google.com/docs/crashlytics/get-started?platform=android#add-plugin
  • 设置 Xcode 以自动上传 dSYM 文件
    https://firebase.google.com/docs/crashlytics/get-started?platform=ios#set-up-dsym-uploading

在 DartPad 里使用 Firebase
借助仅使用 Dart 初始化 FlutterFire 的功能,您现在可以在 DartPad 中使用 Firebase。

上图的示例使用 Flutter、Firebase 和 DartPad (都是无需安装即可使用) 构建了一个小型聊天应用。如今,DartPad 的 Firebase 支持已包含核心 API、身份验证和 Firestore。将来会有更多 Firebase 服务出现在 DartPad 中。


  • Dart 聊天应用示例
    https://dartpad.dev/?id=d57c6c898dabb8c6fb41018588b8cf73
  • 原作者动态
    https://twitter.com/puf/status/1458516522133909506


DartPad 的 FlutterFire 支持还包含在文档中直接嵌入 DartPad 实例的功能:

https://firebase.flutter.dev/docs/firestore/example/

在上面的示例中,您可以看到 Cloud Firestore 的文档和示例应用的代码,您可以直接在浏览器中运行和编辑这些代码,而无需安装内容、创建测试项目,甚至不需要复制/粘贴代码。代码已经在页面中就绪,可以立即使用。


  • 示例应用
    https://github.com/FirebaseExtended/flutterfire/tree/master/packages/cloud_firestore/cloud_firestore/example

Firebase 界面
我们注意到,当人们将 Firebase 集成到他们的应用中时,大多数应用都有某种身份验证流程。其中包括让人们通过电子邮件地址和密码或社交身份验证服务 (例如 Google 提供的服务) 登录。Firebase 身份验证还允许实时创建新帐号、验证电子邮件地址和重置密码,以及支持需要使用短信进行的两步验证、用电话号码登录,甚至能将多个用户帐号合并为一个帐号。Firebase 身份验证支持以上所有的功能,而 Flutter 开发者以前是需要负责为这些功能实现相应界面的。但从今以后就不用了。

现在,我们很高兴地推出 flutterfire_ui package,通过它即可使用少量代码创建基本的身份验证体验。例如,假设您在 Firebase 项目中设置了电子邮件和 Google 身份验证:

  • flutterfire_ui
    https://pub.flutter-io.cn/packages/flutterfire_ui

有了这个配置,您就可以使用如下代码触发身份验证流程:

import 'package:flutter/material.dart';import 'package:firebase_core/firebase_core.dart';import 'package:firebase_auth/firebase_auth.dart';import 'package:flutterfire_ui/auth.dart';import 'firebase_options.dart';
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); runApp(MyApp());}
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key);
@override Widget build(BuildContext context) => MaterialApp( home: AuthenticationGate(), );}
class AuthenticationGate extends StatelessWidget { const AuthenticationGate({Key? key}) : super(key: key);
@override Widget build(BuildContext context) => StreamBuilder<User?>( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) { // User is not signed in - show a sign-in screen if (!snapshot.hasData) { return SignInScreen( providerConfigs: [ EmailProviderConfiguration(), GoogleProviderConfiguration( clientId: 'xxxx-xxxx.apps.googleusercontent.com', ), ], ); }
return HomePage(); // show your app’s home page after login }, );}


在这段代码中,我们初始化了 Firebase,由于用户尚未登录,因此显示登录屏幕。SigninScreen widget 配置了电子邮件登录和 Google 身份验证登录。我们还使用 firebase_auth package 监听用户的身份验证状态,一旦他们完成登录,我们就可以显示应用的其余部分。使用上面这段代码,您就可以为所有支持 Firebase 的平台 (Android、iOS、Web 和 macOS) 提供可用的登录流程。


只需增加一些配置,即可轻松添加图像和自定义文本 (详细信息见文档),从而构建出功能齐备的登录体验:

https://firebase.flutter.dev/docs/ui/overview

上面是移动版本的截图,但由于 flutterfire_ui 屏幕是响应式的,以下即为桌面设备上的界面:

如果用户已经使用电子邮件/密码注册过账号,那他们可以立即登录。如果他们使用 Google 身份验证,无论是在移动设备、Web 还是桌面设备上,系统都会显示常规的 Google 身份验证流程。如果他们还没有帐号,可以按下登录屏幕上的按钮并转到注册屏幕。在他们登录或注册后,会有以下流程可用: 验证电子邮件地址、重置密码、登出和关联社交身份验证帐号。所有平台都适用电子邮件登录,并支持 Google、Facebook 和 Twitter 的社交身份验证,部分支持 Apple (因为它不适用于 Android)。flutterfire_ui 中的身份验证支持多种场景和导航方案,以及自定义和本地化选项。您可以在官方文档中参阅详细文档和示例: 

https://firebase.flutter.dev/docs/ui/overview


并且,身份验证不是 flutterfire_ui 支持的唯一 Firebase 界面相关功能。在向用户展示来自 Firebase 查询的实时、无限滚动的数据列表时,此版本提供 FirestoreListView,您可以使用它在应用中呈现实时查询的结果,如下所示: 

class UserListView extends StatelessWidget { UserListView({Key? key}) : super(key: key);
// live Firestore query final usersCollection = FirebaseFirestore.instance.collection('users');
@override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: const Text('Contacts')), body: FirestoreListView<Map>( query: usersCollection, pageSize: 15, primary: true, padding: const EdgeInsets.all(8), itemBuilder: (context, snapshot) { final user = snapshot.data();
return Column( children: [ Row( children: [ CircleAvatar( child: Text((user['firstName'] ?? 'Unknown')[0]), ), const SizedBox(width: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( '${user['firstName'] ?? 'unknown'} ' '${user['lastName'] ?? 'unknown'}', style: Theme.of(context).textTheme.subtitle1, ), Text( user['number'] ?? 'unknown', style: Theme.of(context).textTheme.caption, ), ], ), ], ), const Divider(), ], ); }, ), );}


实际运行效果如下: 

或者,如果您想为用户提供在表格中创建、读取、更新和删除条目的功能,可以使用 FirestoreDataTable: 

class FirestoreTableStory extends StatelessWidget { FirestoreTableStory({Key? key}) : super(key: key);
// live Firestore query final usersCollection = FirebaseFirestore.instance.collection('users');
@override Widget build(BuildContext context) { return FirestoreDataTable( query: usersCollection, columnLabels: const { 'firstName': Text('First name'), 'lastName': Text('Last name'), 'prefix': Text('Prefix'), 'userName': Text('User name'), 'email': Text('Email'), 'number': Text('Phone number'), 'streetName': Text('Street name'), 'city': Text('City'), 'zipCode': Text('Zip code'), 'country': Text('Country'), }, ); }}


运行结果如下所示:

有关身份验证、列表视图和数据表的详细信息,请查看 flutterfire_ui 文档。由于这是一个预览版,我们计划添加更多功能。如果您有问题或功能需求,请前往 GitHub repo 的讨论专区提交或提出问题。


  • flutterfire_ui 文档
    https://firebase.flutter.dev/docs/ui/overview/
  • GitHub repo
    https://github.com/FirebaseExtended/flutterfire/discussions/6978

Firestore 对象/文档映射
最后,我们在 Firebase 和 Flutter 的集成方面添加了一个新功能: Firestore 对象/文档映射器的 Alpha 版。Firestore ODM 旨在通过熟悉的类型安全、结构化对象和方法简化 Firestore 的使用,从而帮助 Flutter 开发者提高工作效率。Firestore ODM 使用代码生成,允许您用类型安全的方式对数据建模,从而改进与文档和集合交互的语法:
@JsonSerializable()class Person { Person({required this.name, required this.age});
final String name; final int age;}
@Collection<Person>(‘/persons’)final personsRef = PersonCollectionReference();
  • Firestore ODM

    https://firebase.flutter.dev/docs/firestore-odm/overview/


这些类型就位后,您就可以执行类型安全查询:

personsRef.whereName(isEqualTo: 'Bob');personsRef.whereAge(isGreaterThan: 42);

ODM 还支持定义强类型子集,且提供内置选项,通过 select 功能优化 widget 重建。您可以在 Firestore ODM 文档中了解所有这些功能及更多内容。由于这是一个 Alpha 版,我们正在寻求早期反馈,欢迎加入 FlutterFire 讨论中的 Firestore ODM 会话以提供反馈和提问。


  • Firestore ODM 文档
    https://firebase.flutter.dev/docs/firestore-odm/overview/
  • Firestore ODM 会话
    https://github.com/FirebaseExtended/flutterfire/discussions/7475



桌面端


Flutter 2.8 版本朝着桌面端 (Windows、macOS 和 Linux) 的稳定支持又前进了一大步。我们对质量的要求很高,包括国际化和本地化支持,例如我们新增的中文、韩文以及日文汉字 IME 支持。或者又比如我们正在构建的对 Windows 无障碍支持的紧密整合。仅仅让稳定渠道的 Flutter 在桌面设备上运行是不够的 (即便它已经能在带标识的 beta 渠道运行了),它还必须针对世界各地的语言和文化以及不同能力的用户提供良好的运行状态。Flutter 桌面端支持在质量方面尚未达到预期的水平,但我们正在向这个目标迈进!


  • #29620: 中文 IME 支持
    https://github.com/flutter/engine/pull/29620
  • #24713: 韩文 IME 支持
    https://github.com/flutter/engine/pull/24713
  • #29761: 日文汉字 IME 支持
    https://github.com/flutter/engine/pull/29761
  • #77838: Windows 无障碍支持
    https://github.com/flutter/flutter/issues/77838
  • Stable 渠道包含了一份 Beta 渠道的桌面支持
    https://flutter.cn/docs/desktop#beta-snapshot-in-stable-channel


为了让桌面端支持进入稳定版本,我们做了许多工作,其中包括完全重新构建 Flutter 处理键盘事件的架构,以实现同步响应。如此一来就可以用 widget 来处理按键,并取消其在树的其他部分的传递。这方面的成果首先出现在 Flutter 2.5 中,并在 Flutter 2.8 中修复了一些问题和回归,实现了稳定的质量。除此之外,我们还在重新设计特定设备的键盘输入处理方式,以及重构 Flutter 处理文本编辑的方式,所有这些对于键盘输入密集型的桌面应用都很有必要。


  • 处理同步键盘事件

    https://docs.google.com/document/d/1rWXSjkb2ZKv-cpg26lVK0aZi4cVeXJ8j7YmSJdq2TOM/edit#heading=h.pub7jnop54q0

  • #33521: 需要一个从嵌入器发送同步键盘事件至 Dart 并获得响应的方法

    https://github.com/flutter/flutter/issues/33521

  • #44918: 特定设备的键盘事件应该在嵌入器中发生

    https://github.com/flutter/flutter/issues/44918

  • #86736: 文本编辑模型重构

    https://github.com/flutter/flutter/pull/86736


此外,我们还持续扩展了 Flutter 的视觉密度支持,并开放对话框的对齐方式,这都是为了实现更适用于桌面设备的界面。

  • #89353: 增加 visualDensity、focusNode 和 enableFeedback 
    https://github.com/flutter/flutter/pull/89353
  • #88984: 允许对话框进行自定义对齐
    https://github.com/flutter/flutter/pull/88984

最后,Flutter 团队并不是唯一致力于 Flutter 桌面端支持的团队。举个例子,Canonical 的桌面团队正在与 Invertase 合作,致力在 Linux 和 Windows 上实现最流行的 Flutter Firebase 插件。

您可以在 Invertase 博客中进一步了解其预览版:

https://invertase.io/blog/announcing-flutterfire-desktop



DartPad


完整的 Flutter 版本发布必然涉及工具方面的改进。在此版本中,DartPad 最大的改进是对更多 package 的支持。事实上,现在支持导入的 package 达到了 23 个。除了对几个 Firebase 服务的支持外,还支持 bloc、characters、collection、google_fonts 和 flutter_riverpod 等流行的 package。DartPad 团队将继续增加新的 package,如果您想查看目前支持哪些 package,可以点击下方截图右下角的信息图标:

如果您想要了解 DartPad 支持新 package 的计划,请查看 Dart wiki 上的这篇文章:

https://github.com/dart-lang/dart-pad/wiki/Adding-support-for-a-new-package

DartPad 还有一个相当实用的新特性。此前,DartPad 一直运行最新的稳定版本。在这个版本中,您可以让 DartPad 使用最新的 beta 版或上一个稳定版本 (称为 "旧渠道"),只需使用状态栏中新增的渠道 (Channel) 菜单切换即可。

这一点十分实用,举个例子,假设您正在撰写一篇博文,而最新的稳定版本却有点过时……



移除 dev 渠道


Flutter 的 "渠道 (channel)" 控制着底层 Flutter 框架和引擎在您开发机器上变化的速度,稳定 (stable) 渠道表示最少的流失,而主 (master) 渠道则相反。由于资源限制,我们最近停止了 dev 渠道的更新。虽然我们确实收到了与此相关的一些问题,但我们发现只有不到 3% 的 Flutter 开发者使用该渠道。因此我们决定正式停用 dev 渠道。虽然很少有开发者使用 dev 渠道,但 Flutter 工程师需要花费大量时间和精力来维护它。如果您所有的时间都在使用稳定渠道 (正如 90% 以上的 Flutter 开发者所做的那样),那您根本不会再需要 dev 渠道。放弃这个渠道意味着您可以少做一个决定,而 Flutter 团队可以将时间和精力放在其他事情上。


您可以使用 flutter channel 命令来决定要使用哪个渠道。以下是 Flutter 团队对每个渠道的看法:
  • 稳定 (stable) 渠道代表着我们构建的最高质量。此渠道一般每季度发布一次,期间会对关键问题进行热修复。这是 "慢" 渠道: 安全、成熟、提供长期支持。
  • Beta 渠道为喜欢更快节奏的开发者们提供了一种替代 stable 渠道的快速迭代方案。目前每月发布,在发布前稳定。这是 "快" 渠道。如果我们发现 dev 渠道能满足 beta 渠道目前无法满足的需求,我们可能会改变对 beta 渠道的处理方案来满足这些需求 (例如加快 beta 渠道的发布节奏,以及降低其测试和热修复级别)。
  • 主 (master) 渠道是活跃的开发渠道。我们对此渠道不提供支持,但我们会针对它进行全面的单元测试。能适应不稳定版本的贡献者或高级用户可以使用该渠道。在这个渠道中,我们会快速构建和破坏一些功能 (然后很快将其修复)。

在未来几个月停用 dev 渠道的过程中,请您考虑使用 beta 或主 (master) 渠道,具体取决于您对流失的容忍度,以及您对更新和质量的要求。



重大变更


像往常一样,我们会尽力减少每个版本中重大变更的数量。在 Flutter 2.8 中,除了已经过期并根据我们的重大变更政策移除的已弃用 API 之外,没有其他重大变更:

https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes


  • #90292: 移除被弃用的 autovalidate

  • https://github.com/flutter/flutter/pull/90292


  • #90293: 移除被弃用的 FloatingHeaderSnapConfiguration.vsync

  • https://github.com/flutter/flutter/pull/90293


  • #90294: 移除被弃用的 AndroidViewController.id

  • https://github.com/flutter/flutter/pull/90294

  • http://androidviewcontroller.id/


  • #90295: 移除被弃用的 BottomNavigationBarItem.title

  • https://github.com/flutter/flutter/pull/90295


  • #90296: 移除已弃用的文本输入格式类

  • https://github.com/flutter/flutter/pull/90296


如果您仍在使用这些 API,并且想要详细了解如何更新您的代码,可以阅读迁移指南。非常感谢社区一如既往地提供测试,帮助我们识别以上重大变更。


  • 迁移指南: 2.5 版本之后弃用的 API
    https://flutter.cn/docs/release/breaking-changes/2-5-deprecations
  • 提供测试
    https://github.com/flutter/tests/blob/master/README.md


总结


在我们告别 2021 年并展望 2022 年之际,Flutter 团队要对整个 Flutter 社区的工作和支持表示感谢。诚然,我们正在为世界上越来越多的开发者构建 Flutter,但没有您我们就无法做到这一切。Flutter 社区是独一无二的,我们感谢您所做的一切。祝您假期愉快,我们新的一年见!



推荐阅读

如页面未加载,请刷新重试

 点击屏末 | 阅读原文 | 即刻访问 Flutter 开发者社区中文资源



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存